package smart.rpc.server;

import smart.rpc.common.SmartRPCRequest;
import smart.rpc.common.SmartRPCResponse;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.*;

/**
 * Created By gao_e on 2020/3/8 15:54
 */
public class ServerInvokeRequestCallableTask implements Callable<SmartRPCResponse> {
    // 当前任务的参数——请求数据
    private SmartRPCRequest smartRPCRequest;

    public ServerInvokeRequestCallableTask(SmartRPCRequest smartRPCRequest) {
        this.smartRPCRequest = smartRPCRequest;
    }

    private static final ThreadPoolExecutor handServerTaskTP =
            new ThreadPoolExecutor(1, 3, 3,
                    TimeUnit.SECONDS, new LinkedBlockingDeque<>(100), new ThreadPoolExecutor.CallerRunsPolicy());

    @Override
    public SmartRPCResponse call() throws Exception {
        String serviceFullName = this.smartRPCRequest.getServiceFullName();
        // 从rpc server端容器中获取servie实例
        Object serviceInstance = ServerServiceContainer.getBeanByServiceFullBame(serviceFullName);
        // 构建响应对象
        SmartRPCResponse response = new SmartRPCResponse();
        response.setRequestId(smartRPCRequest.getRequestId());
        response.setSuccess(true);
        response.setMsg("SUCCESS");
        response.setCode(1);
        // 反射执行
        response.setData(this.handle(serviceInstance));
        response.setResultCls(smartRPCRequest.getResultCls());
        response.setRequestTimeStamp(smartRPCRequest.getRequestTimeStamp());
        // 返回线程执行结果
        return response;
    }
    /**
     * 反射执行调用 处理远程请求
     */
    private Object handle(Object service)
            throws ClassNotFoundException, NoSuchMethodException, SecurityException,
            IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        String interfaceName = this.smartRPCRequest.getItfcName();
        Class<?> serviceInterfaceClass = Class.forName(interfaceName);
        // 获取方法名称
        String methodName = this.smartRPCRequest.getMethodName();
        Object[] data = this.smartRPCRequest.getArgs();
        Class<?>[] parameterTypes = this.smartRPCRequest.getMethodParameTypes();
        // 获取方法对象
        Method method = serviceInterfaceClass.getMethod(methodName, parameterTypes);
        method.setAccessible(true);
        // 反射执行方法
        Object result = method.invoke(service, data);
        return result;
    }

    // 使用线程池执行任务，并且同步等待任务
    public SmartRPCResponse add2InnerPrivateThreadPoolAndExecuteSelf()
            throws InterruptedException, ExecutionException, TimeoutException {
        // 采用线程池对当前任务进行处理
        Future<SmartRPCResponse> future = handServerTaskTP.submit(this);
        SmartRPCResponse smartRPCResponse = future.get(3, TimeUnit.SECONDS);
        return smartRPCResponse;
    }

}
